package com.cs.framework.core.context;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.support.AbstractXmlApplicationContext;

import com.cs.framework.common.util.StringUtils;
import com.cs.framework.core.config.PropertyConfig;
import com.cs.framework.core.context.xml.ModuleDocumentLoader;
import com.cs.framework.core.util.CoreConstant;

/**
 * 模块上下文
 * 
 * @author hedongzhou
 * 
 */
public class CoreModule extends AbstractXmlApplicationContext implements Module, BeanDefinitionRegistry {

	/**
	 * 应用上下文
	 */
	protected Application application;

	/**
	 * 模块Id
	 */
	protected String moduleId;

	/**
	 * 模块package路径，以“.”分隔
	 */
	protected String packagePath;

	/**
	 * 模块package系统路径，以“/”分隔
	 */
	protected String packageUrl;

	/**
	 * 模块配置路径
	 */
	protected String moduleConfig;

	/**
	 * 属性配置信息
	 */
	protected Map<String, Object> propertyMap = new HashMap<String, Object>();

	/**
	 * 扫描
	 */
	protected ClassPathBeanDefinitionScanner scanner;

	public CoreModule(Application application, String moduleId, String packagePath) {
		super((ApplicationContext) application);

		this.application = application;
		this.moduleId = moduleId;
		this.packagePath = packagePath;
		this.packageUrl = packagePath.replaceAll("\\.", "/");
		this.moduleConfig = StringUtils.concatConfigPath(CoreConstant.CLASSPATH_PATTERN + this.packageUrl
				+ CoreConstant.MODULE_SPRING_CUSTOM_CONF, application.getModuleCommonConfig());
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * 初始化
	 */
	public void init() {
		// 初始化上下文配置
		initContextConfig();

		// 初始化属性配置信息
		initProperties();
	}

	/**
	 * 初始化上下文配置
	 */
	protected void initContextConfig() {
		// 加载spring配置
		setConfigLocations(moduleConfig.split(CoreConstant.CONF_SEPARATE));
		refresh();
	}

	/**
	 * 初始化属性配置信息
	 */
	protected void initProperties() {
		propertyMap.putAll(application.getPropertyMap());

		try {
			// 根据配置，获取属性配置对象
			PropertyConfig propConfig = (PropertyConfig) getBean(CoreConstant.CS_PROPERTY);
			propertyMap.putAll(propConfig.gePropertyMap());
		} catch (NoSuchBeanDefinitionException e) {
		}
	}

	/**
	 * 重写invokeBeanFactoryPostProcessors方法
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		super.invokeBeanFactoryPostProcessors(beanFactory);

		// 扫描路径
		scanner.scan(packagePath);
	}

	/**
	 * 重写loadBeanDefinitions方法
	 */
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		// 配置自定义的XML解析器
		reader.setDocumentLoader(new ModuleDocumentLoader());

		super.loadBeanDefinitions(reader);
	}

	/**
	 * 获取属性配置信息
	 */
	public Map<String, Object> getPropertyMap() {
		return propertyMap;
	}

	/**
	 * 获取属性配置信息
	 * 
	 * @param key
	 *            键值
	 * @return
	 */
	public Object getProperty(String key) {
		return propertyMap.get(key);
	}

	/**
	 * 获取模块Id
	 * 
	 * @return
	 */
	public String getModuleId() {
		return moduleId;
	}

	/**
	 * 模块package路径，以“.”分隔
	 * 
	 * @return
	 */
	public String getPackagePath() {
		return packagePath;
	}

	/**
	 * 模块package系统路径，以“/”分隔
	 * 
	 * @return
	 */
	public String getPackageUrl() {
		return packageUrl;
	}

	/**
	 * 获取应用上下文
	 * 
	 * @return
	 */
	public Application getAppContext() {
		return application;
	}

	// ---------------------------------------------------------------------
	// Implementations of BeanDefinitionRegistry's methods
	// ---------------------------------------------------------------------
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		return getBeanFactory().getBeanDefinition(beanName);
	}

	public boolean isBeanNameInUse(String beanName) {
		return ((DefaultListableBeanFactory) getBeanFactory()).isBeanNameInUse(beanName);
	}

	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		((DefaultListableBeanFactory) getBeanFactory()).registerBeanDefinition(beanName, beanDefinition);
	}

	public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		((DefaultListableBeanFactory) getBeanFactory()).removeBeanDefinition(beanName);
	}

	public boolean isAlias(String beanName) {
		return ((DefaultListableBeanFactory) getBeanFactory()).isAlias(beanName);
	}

	public void registerAlias(String beanName, String alias) {
		((DefaultListableBeanFactory) getBeanFactory()).registerAlias(beanName, alias);
	}

	public void removeAlias(String alias) {
		((DefaultListableBeanFactory) getBeanFactory()).removeAlias(alias);
	}

}
